package com.common.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 阿里云 OSS 工具类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSUtils {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    /**
     * 实现上传图片到OSS
     */
    /**
     * @param file 前端传递过来的文件
     * @return 图片的阿里云oss地址url
     * @throws IOException
     */
    public String upload(MultipartFile file) throws IOException {
        try {
            // 获取上传的文件的输入流
            InputStream inputStream = file.getInputStream();

            // 避免文件覆盖
            String originalFilename = file.getOriginalFilename();
            String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

            // 创建 OSSClient 实例
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

            // 上传文件到 OSS
            ossClient.putObject(bucketName, fileName, inputStream);

            // 文件访问路径
            String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;

            // 关闭 OSSClient
            ossClient.shutdown();

            log.info("文件上传成功，路径为：{}", url);

            return url;
        } catch (OSSException oe) {
            log.error("Caught an OSSException. Error Message:{}", oe.getErrorMessage());
            log.error("Error Code:{}", oe.getErrorCode());
            log.error("Request ID:{}", oe.getRequestId());
            log.error("Host ID:{}", oe.getHostId());
            throw new IOException("OSS 上传异常", oe);
        } catch (ClientException ce) {
            log.error("Caught an ClientException. Error Message:{}", ce.getMessage());
            throw new IOException("OSS 客户端异常", ce);
        }
    }

    /**
     * 移动文件到新的目录
     *
     * @param srcKey  原始文件的key
     * @param destKey 目标文件的key
     * @throws IOException
     */
    public void moveFile(String srcKey, String destKey) throws IOException {
        try {
            // 创建 OSSClient 实例
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

            // 复制文件
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketName, srcKey, bucketName, destKey);
            CopyObjectResult copyObjectResult = ossClient.copyObject(copyObjectRequest);

            // 删除原始文件
            ossClient.deleteObject(bucketName, srcKey);

            // 关闭 OSSClient
            ossClient.shutdown();

            log.info("文件移动成功，原始文件已删除");
        } catch (Exception oe) {
            throw new IOException("OSS 移动文件异常", oe);
        }
    }

    /**
     * 删除OSS上的文件夹（前缀匹配的所有文件）
     *
     * @param directoryPrefix 目录前缀，例如 "dj/video/1000427/"
     * @throws IOException
     */
    public void deleteDirectory(String directoryPrefix) throws IOException {
        try {
            // 创建 OSSClient 实例
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

            // 获取文件夹下的所有文件
            List<String> objectKeys = listObjectKeys(ossClient, directoryPrefix);
            if (objectKeys != null && !objectKeys.isEmpty()) {
                // 批量删除文件
                DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName);
                deleteRequest.setKeys(objectKeys);
                DeleteObjectsResult deleteResult = ossClient.deleteObjects(deleteRequest);

                // 关闭 OSSClient
                ossClient.shutdown();
            }
        } catch (Exception oe) {
            log.error("OSS 删除文件夹异常", oe);
            throw new IOException("OSS 删除文件夹异常", oe);
        }
    }

    /**
     * 列出给定前缀的所有文件key
     *
     * @param ossClient        OSS客户端实例
     * @param directoryPrefix 文件夹前缀
     * @return 文件key列表
     */
    private List<String> listObjectKeys(OSS ossClient, String directoryPrefix) {
        List<String> objectKeys = new ArrayList<>();
        // 列出所有文件
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName)
                .withPrefix(directoryPrefix);
        List<OSSObjectSummary> objectSummaries = ossClient.listObjects(listObjectsRequest).getObjectSummaries();

        for (OSSObjectSummary objectSummary : objectSummaries) {
            objectKeys.add(objectSummary.getKey());
        }
        return objectKeys;
    }
}

